package QianFeng04;

/**
 * 多态
 * 多态是同一个行为具有多个不同表现形式或形态的能力
 * 多态就是同一个接口，使用不同的实例而执行不同操作
 * <p>
 * 多态性可以大概分为两类：
 * 1、方法的重写和重载
 * 2、对象的多态性
 *
 * 多态性小结:
 * 1、方法的重裁与重写就是方法的多态性表现
 * 2、多个子类就是父类中的多种形态
 * 3、父类引用可以指向子类对象，自动转换
 * 4、开类对象指向父类引用需要强制转换(注意:类型不对会报异常)
 * 5、在实际开发中尽量使用父类引用(更利于扩展)
 *
 * 结论：
 * 1、在编程时针对抽象类型的编写代码，称为面向抽象编程( 或面向接口编程)
 * 2、父类通常都定义为抽象类、接口
 *
 * 对象的多态性：对象多态性是从继承关系中的多个类而来
 * 向上转型：将子类实例转为父类引用
 * 格式：父类 父类对象=子类实例; ->自动转换
 * 以基本数据类型操作为例: int i='a';
 * (因为char的容量比int小，所以可以自动完成)
 *
 * 向下转型:：将父类实例转为子类实例
 * 格式：子类子类对象= (子类)父类实例; 强制转换
 * 以基本数据类型操作为例: char c =(char)97;
 * 因为整型是4个字节比char 2个字节要大，所以需要强制完成
 *
 * instanceof
 * 是用于检查对象是否为指定的类型，通常在把父类引用强制转换为子类引用时要使用，以避免发生类型
 *     转换异常(ClassCastException)
 * 语法格式如下:
 * 对象 instanceof 类型 ---返回boolean类型值
 **/
public class Test6 {
    public static void main(String[] args) {
        //用父类的引用指向子类的对象（用大的类型来表示小的类型），自动转换（向上转型）
        Chicken hc = new HomeChicken("小家鸡");
        //hc.eat();
        Chicken yc = new YeChicken("小野鸡");
        //yc.eat();

        //hc = yc;
        //hc.eat();

        //抽象引用
        eat(hc);
        eat(yc);

        Chicken sc = new ScreamChicken("尖叫鸡");
        eat(sc);
    }

    //抽象（粒度） 面向抽象编程（面向接口编程）
    public static void eat(Chicken chicken) {
        System.out.println("鸡吃饭");
        chicken.eat();
        //当我们需要把父类的实例强制转换为子类引用时，为了避免类型转换异常，需要在转换前判断
        if (chicken instanceof ScreamChicken) {//成立的条件是，对象本身及对象的父类型，都可以通过检查
            ScreamChicken screamChicken = (ScreamChicken)chicken; //大的类型转换为小的类型（强制转换）
            screamChicken.song();
        }

    }
}

//鸡
abstract class Chicken {
    private String name;

    public Chicken() {
    }

    public Chicken(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract void eat();
}

//家鸡
class HomeChicken extends Chicken {
    public HomeChicken(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println(this.getName() + "，我爱吃米");
    }
}

//野鸡
class YeChicken extends Chicken {
    public YeChicken(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println(this.getName() + "，我爱吃虫子");
    }
}

//尖叫鸡
class ScreamChicken extends Chicken {
    public ScreamChicken(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println(this.getName() + "，我不吃东西");
    }

    public void song(){
        System.out.println("唧唧复唧唧，我要开始尖叫了！");
    }
}